home *** CD-ROM | disk | FTP | other *** search
- /*
- ** multidef.c - A program to scan a collection of .o and library files
- ** and search for multiply defined symbols.
- ** This can catch problems where a symbol is defined in your
- ** routine as well as in a scanned library (for example you
- ** have a roued executables have hunks
- ** in them that this program doesn't understand, besides the
- ** symbol information is gone from an executable anyway.
- **
- ** Copyright (c) 1886, Paul Jatkowski.
- */
- #include <stdio.h>
- #include <fcntl.h>
-
- /* defines for the different hunk types */
-
- #define HUNK_UNIT 0x3e7 /* start of a program unit */
- #define HUNK_NAME 0x3e8 /* name of hunk (optional) */
- #define HUNK_CODE 0x3e9 /* block of code, possibly to be relocated */
- #define HUNK_DATA 0x3ea /* block of initialized data, possibly relocated */
- #define HUNK_BSS 0x3eb /* uninitialized data */
- #define HUNK_RELOC32 0x3ec /* 32 bit relocation entries */
- #define HUNK_RELOC16 0x3ed /* 16 bit pc relative relocation entries */
- #define HUNK_RELOC8 0x3ee /* 8 bit pc relative relocation entries */
- #define HUNK_EXT 0x3ef /* external symbol info ... see below */
- #define HUNK_SYMBOL 0x3f0 /* symbol table info, optional, for debuggers */
- #define HUNK_DEBUG 0x3f1 /* further debugging info */
- #define HUNK_END 0x3f2 /* end of a hunk */
- /* lattice 3.1 hunk types */
- #define HUNK_DRELOC32 0x3f7 /* 32 bit data section relative relocation */
- #define HUNK_DRELOC16 0x3f8 /* 16 bit data section relative relocation */
- #define HUNK_DRELOC8 0x3f9 /* 8 bit data section relative relocation */
-
- /* the following hunk defines are for load files */
- #define HUNK_HEADER 0x3f3 /* info for loader ... lots of stuff in here */
- #define HUNK_OVERLAY 0x3f5 /* overlay table for overlay programs */
- #define HUNK_BREAK 0x3f6 /* end of overlay node */
-
-
- /* defines for HUNK_EXT hunk
- ** These are the important ones for getting symbol define/reference info
- */
-
- #define EXT_SYMB 0 /* symbol table */
- #define EXT_DEF 1 /* relocatable definition */
- #define EXT_ABS 2 /* absolute definition */
- #define EXT_RES 3 /* resident library definition */
- #define EXT_REF32 129 /* 32 bit reference to symbol */
- #define EXT_COMMON 130 /* 32 bit reference to COMMON */
- #define EXT_REF16 131 /* 16 bit reference to symbol */
- #define EXT_REF8 132 /* 8 bit reference to symbol */
- /* lattice 3.1 extra defines */
- #define EXT_DREF32 133 /* 32 bit base relative to symbol */
- #define EXT_DREF16 134 /* 16 bit base relative to symbol */
- #define EXT_DREF8 135 /* 8 bit base relative to symbol */
-
-
- #define MAXBUF 100 /* buffer for "get_and_flush" and "myread" */
- long buf[MAXBUF];
-
- /* operation flags */
- int pr_def = 0; /* print symbol definition listing */
- int pr_ref = 0; /* print symbol reference listing */
-
- /* defines for t_insert routine (binary tree) */
- struct t_node {
- struct tnode *right;
- struct tnode *left;
- char *key; /* symbol name */
- char *aux1; /* file name */
- char *aux2; /* module name */
- };
- typedef struct t_node T_node;
-
- /* declarations for forward referenced routines */
- T_node *t_insert();
- void save_def();
-
- void
- myread(fd,ptr,sz)
- int fd,sz;
- char *ptr;
- {
- if (read(fd,ptr,sz) != sz)
- {
- printf("short read: aborting\n");
- exit(10);
- }
- }
-
- /* read n LONGS from the object file, used to flush unnecessary sections.
- ** I suppose that a seek would work also...... */
- void
- get_and_flush(objfile,n)
- int objfile,n;
- {
- int n1;
- n *= 4;
- while (n > 0)
- {
- n1 = n > MAXBUF ? MAXBUF : n;
- n -= n1;
- myread(objfile,buf,n1);
- }
- }
- /*
- ** given a object or library file name, read it and find symbol entries.
- ** print references or definitions if the flags are set. Collect the
- ** to look for multiple defines
- */
- void
- procfile(fname)
- char *fname;
- {
- int moretodo = 1;
- long d1 = -1 ,d2;
- int ext_type;
- char curhunk[100];
- char curname[100];
- int hunkend = 0;
- int objfile;
-
- if (pr_def || pr_ref)
- printf("\t=========== processing %s ============\n",fname);
-
- if ( (objfile = open(fname,O_RDONLY)) < 0)
- {
- perror("can't open input file");
- poserr("amiga error");
- return;
- }
-
- while (moretodo)
- {
- /* read what is hopefully a hunk type */
- if (read(objfile,(char *)&d1,sizeof(d1)) != sizeof(d1))
- {
- if (!hunkend)
- printf("Unexpected end of file! (no hunk end)\n");
- moretodo = 0;
- continue;
- }
- hunkend = 0;
- switch(d1)
- {
- case HUNK_UNIT: /* 3e7 Start of program unit */
- myread(objfile,&d1,sizeof(d1));
- myread(objfile,buf,d1*4);
- buf[d1] = 0;
- strcpy(curhunk,(char *)buf);
- #ifdef DEBUG
- printf("hunk unit: %s\n",curhunk);
- #endif
- break;
-
- case HUNK_NAME: /* 3e8 Name of a hunk */
- myread(objfile,&d1,sizeof(d1));
- myread(objfile,buf,d1*4);
- buf[d1] = 0;
- strcpy(curname,(char *)buf);
- #ifdef DEBUG
- printf("hunk name: %s\n",curname);
- #endif
- break;
-
- case HUNK_CODE: /* 3e9 Code segment */
- case HUNK_DATA: /* 3ea Initialized Data segment */
- myread(objfile,&d1,sizeof(d1));
- #ifdef DEBUG
- printf("code/data hunk length=%d\n",d1);
- #endif
- get_and_flush(objfile,d1);
- break;
-
- case HUNK_BSS: /* 3eb Unitialized Data segment */
- myread(objfile,&d1,sizeof(d1));
- #ifdef DEBUG
- printf("bss section length=%d\n",d1);
- #endif
- break;
-
- case HUNK_RELOC32: /* 3ec 32-bit relocation list */
- case HUNK_RELOC16: /* 3ed 16-bit PC-relative relocation info */
- case HUNK_RELOC8: /* 3ee 8-bit PC-relative relocation info */
- case HUNK_DRELOC32:
- case HUNK_DRELOC16:
- case HUNK_DRELOC8:
- #ifdef DEBUG
- printf("reloc hunk type 0x%x\n",d1);
- #endif
- myread(objfile,&d1,sizeof(d1));
- while (d1 != 0)
- {
- myread(objfile,&d2,sizeof(d2));
- get_and_flush(objfile,d1);
- myread(objfile,&d1,sizeof(d1));
- }
- break;
-
- case HUNK_EXT: /* 3ef External symbol info */
- #ifdef DEBUG
- printf("hunk ext\n");
- #endif
- myread(objfile,&d1,sizeof(d1));
- while (d1 != 0)
- {
- ext_type = (d1 >> 24) & 0xff;
- d1 &= 0xffffff;
- switch(ext_type)
- {
- case EXT_SYMB: /* symbol table */
- get_and_flush(objfile,d1+1);
- break;
- case EXT_DEF: /* reloc def */
- case EXT_ABS: /* abs def */
- case EXT_RES: /* resident lib */
- myread(objfile,buf,d1*4);
- buf[d1] = 0;
- if (pr_def)
- printf("DEF %-45.45s: %s\n",(char *)buf,curhunk);
- save_def(fname,curhunk,(char *)buf);
- get_and_flush(objfile,1);
- break;
- case EXT_REF32: /* 32 bit ref */
- case EXT_REF16: /* 16 bit ref */
- case EXT_REF8: /* 8 bit ref */
- case EXT_DREF32:
- case EXT_DREF16:
- case EXT_DREF8:
- myread(objfile,buf,d1*4);
- buf[d1] = 0;
- if (pr_ref)
- printf("REF %-45.45s: %s\n",(char *)buf,curhunk);
-
- myread(objfile,&d1,sizeof(d1));
- get_and_flush(objfile,d1);
- break;
- case EXT_COMMON: /* 32 bit ref */
- myread(objfile,buf,d1*4);
- buf[d1] = 0;
- if (pr_def)
- printf("COM %-45.45s: %s\n",(char *)buf,curhunk);
- save_def(fname,curhunk,(char *)buf);
-
- myread(objfile,&d1,sizeof(d1));
- myread(objfile,&d1,sizeof(d1));
- get_and_flush(objfile,d1);
- break;
- default:
- printf("ERROR: unknown HUNK_EXT 0x%x\n",d1);
- }
- myread(objfile,&d1,sizeof(d1));
- }
- break;
-
- case HUNK_SYMBOL: /* 3f0 Symbol table info */
- myread(objfile,&d1,sizeof(d1));
- while (d1 != 0)
- {
- get_and_flush(objfile,d1+1);
- myread(objfile,&d1,sizeof(d1));
- }
- break;
-
- case HUNK_DEBUG: /* 3f1 Debug data */
- myread(objfile,&d1,sizeof(d1));
- get_and_flush(objfile,d1);
- break;
-
- case HUNK_END: /* 3f2 End of this hunk */
- hunkend++;
- break;
- case HUNK_HEADER: /* 3f3 hunk summary info for loader */
- case HUNK_OVERLAY: /* 3f5 overlay table info */
- case HUNK_BREAK: /* 3f6 end of overlay node */
- default:
- printf("ERROR: can't handle hunk 0x%x\n",d1);
- }
-
- }
- close(objfile);
- }
-
- #define MAXEXP 100
-
- void
- main(argc,argv)
- int argc;
- char *argv[];
- {
- int i,j;
- int matches;
- char names[3000]; /* for expanded file names */
- char *namep[MAXEXP]; /* array for pointers to file names */
-
- /* parse args, set global flags */
-
- if ( argc < 2)
- {
- printf("usage: %s [-d] [-r] objfile1 ojbfile2 ...\n",argv[0]);
- exit(1);
- }
- /*
- ** Arg processing, nothing great, but sufficient.
- */
- for (i = 1 ; i < argc ; i++)
- {
- if (strcmp(argv[i],"-r") == 0)
- {
- pr_ref = 1;
- continue;
- }
- if (strcmp(argv[i],"-d") == 0)
- {
- pr_def = 1;
- continue;
- }
- /*
- ** not an arg, must be an object file.
- ** Lattice 3.10 provides the getfnl routine that will take
- ** an amigados pattern and build a list of matching files.
- ** It this is not available, the input file name could be
- ** passed directly to procfile, but the wild card expansion
- ** is nice.
- */
- matches = getfnl(argv[i],names,sizeof(names),0);
- if (matches > 0)
- {
- /* set up pointer array to point to each string */
- if (strbpl(namep,MAXEXP,names) != matches)
- {
- printf("%s - expansion overflow\n",argv[i]);
- continue;
- }
- /* sort the pointers, just to be nice */
- strsrt(namep,matches);
-
- /* process the files .... */
- for ( j = 0 ; j < matches ; j++)
- procfile(namep[j]);
- }
- else
- {
- printf("expansion failed for %s\n",argv[i]);
- }
- }
- }
-
- /*
- ** build a tree node and call t_insert to put it into the tree of defs.
- ** if t_insert returns 0, this is the only definition of the symbol.
- ** if t_insert returns -1, there was some unexpected error in t_insert.
- ** if t_insert returns anything else, it's a pointer to a node containing
- ** the first definiton of the symbol. The current entry is not saved
- ** in the tree.
- */
- void
- save_def(fname,hunk,sym)
- char *fname, *hunk, *sym;
- {
- /* this routine does the work of building an internal symbol table */
- static T_node t1;
- static T_node *tree = (T_node *)0;
- T_node *rval;
-
- t1.key = sym;
- t1.aux1 = fname;
- t1.aux2 = hunk;
- t1.right = (T_node *)0;
- t1.left = (T_node *)0;
- rval = t_insert(&tree,&t1);
- if ((int) rval != 0 && (int)rval != -1)
- {
- printf("%s defined in %s(%s) and %s(%s)\n",
- sym,rval->aux1,rval->aux2,fname,hunk);
- }
- }
-
- /*
- ** Insert a node into a binary tree. The tree built is never walked so only
- ** the insert routine is needed
- */
- T_node *
- t_insert(head,node)
- T_node **head; /* note double indirection, this simplfies the code later */
- T_node *node;
- {
- T_node *newnode;
- static char *O_aux1 = (char *)0;
- static char *O_aux2 = (char *)0;
- int result;
- #ifdef DEBUG
- printf("key=%s aux1=%s aux2=%s\n",node->key,node->aux1,node->aux2);
- #endif
- /* check for null head pointer, if so create first node */
- if (*head == (T_node *)0)
- {
- newnode = (T_node *)malloc(sizeof(T_node));
- if (newnode == (T_node *)0)
- return((T_node *)-1);
-
- newnode->key =
- (char *) malloc(strlen(node->key)+1);
- strcpy(newnode->key,node->key);
-
- newnode->aux1 = O_aux1 = (char *)malloc(strlen(node->aux1)+1);
- strcpy(newnode->aux1,node->aux1);
-
- newnode->aux2 = O_aux2 = (char *)malloc(strlen(node->aux2)+1);
- strcpy(newnode->aux2,node->aux2);
- #ifdef DEBUG
- printf ("newnode =0x%x\n",newnode);
- #endif
- newnode->right = (T_node *)0;
- newnode->left = (T_node *)0;
- *head = newnode;
- return(0);
- }
- /* walk the tree to find a good spot */
- while (*head != (T_node *)0)
- {
- #ifdef DEBUG
- printf ("TOL: head=0x%x *head=0x%x compare <%s> <%s>\n",
- head,*head,(*head)->key,node->key);
- #endif
- if ( (result = strcmp((*head)->key,node->key)) == 0)
- {
- return(*head); /* return pointer to dup node */
- }
- #ifdef DEBUG
- printf ("result=%d\n",result);
- #endif
- if (result >0)
- head = (T_node **)&(*head)->right;
- else
- head = (T_node **)&(*head)->left;
- }
- #ifdef DEBUG
- printf ("EOL: head=0x%x *head=0x%x\n",head,*head);
- #endif
- /* didn't find it, link it in....
- ** only allocate new space for file and module name if different than
- ** last one remembered, otherwise use the previous string */
- if ( (*head = (T_node *)malloc(sizeof(T_node))) == (T_node *)0)
- {
- printf("can't allocate space for node!\n");
- return((T_node *)0);
- }
- (*head)->key = (char *)malloc(strlen(node->key)+1);
- strcpy((*head)->key,node->key);
-
- if (strcmp(node->aux1,O_aux1) == 0)
- (*head)->aux1 = O_aux1; /* same thing! */
- else
- {
- (*head)->aux1 = (char *)malloc(strlen(node->aux1)+1);
- strcpy((*head)->aux1,node->aux1);
- }
- if (strcmp(node->aux2,O_aux2) == 0)
- (*head)->aux2 = O_aux2; /* same thing! */
- else
- {
- (*head)->aux2 = (char *)malloc(strlen(node->aux2)+1);
- strcpy((*head)->aux2,node->aux2);
- }
- (*head)->right = (T_node *)0;
- (*head)->left = (T_node *)0;
- return((T_node *)0);
- }
- r array to point to each string */
- if (strbpl(namep,MAXEXP